package com.digitalbonestudios.slugpug.tv;

import java.util.List;
import java.util.Random;

import javax.microedition.khronos.opengles.GL10;

import com.digitalbonestudios.framework.Game;
import com.digitalbonestudios.framework.Input.KeyEvent;
import com.digitalbonestudios.framework.Input.TouchEvent;
import com.digitalbonestudios.framework.gl.Camera2D;
import com.digitalbonestudios.framework.gl.SpriteBatcher;
import com.digitalbonestudios.framework.gl.TextureRegion;
import com.digitalbonestudios.framework.impl.GLScreen;
import com.digitalbonestudios.framework.math.Rectangle;
import com.digitalbonestudios.framework.math.Vector2;
import com.digitalbonestudios.framework.math.OverlapTester;

public class SlugPug extends GLScreen {
	enum GameState {
		Ready,
		Running,
		Paused,
		GameOver
	}
	
	enum MenuSelection {
		Resume,
		PlayAgain,
		Quit
	}

	private float initialX = 0;  
	private float initialY = 0;  
	private float deltaX = 0;  
	private float deltaY = 0;
	
	private final float GAMEOVER_DELAY = 2500f;
	long gameOverTime = 0;
	boolean gameOverDelayReached = false;

	GameState state = GameState.Ready;

	int oldScore = 0;
	String score = "0";

	Camera2D guiCam;
	Vector2 touchPoint;
	SpriteBatcher batcher;
	World world;
	WorldRenderer renderer;

	GenericObject pauseButton;
	GenericObject soundButton;
	GenericObject playAgainButton;
	GenericObject resumeButton;
	GenericObject quitButton;
	GenericObject playAgainIndicator;
	GenericObject resumeIndicator;
	GenericObject quitIndicator;
	
	MenuSelection _menuSelection = MenuSelection.Resume;
	
	Random random;

	public SlugPug(Game game) {
		super(game);
		guiCam = new Camera2D(glGraphics, 768, 448);

		touchPoint = new Vector2();
		batcher = new SpriteBatcher(glGraphics, 1000);
		world = new World();
		renderer = new WorldRenderer(glGame.getContext(), glGraphics, batcher, world);

		pauseButton = new GenericObject(32, 416, 64, 64);
		soundButton = new GenericObject(112, 416, 64, 64);
		playAgainButton = new GenericObject(384, 288, 448, 64);
		resumeButton = new GenericObject(384, 288, 320, 64);
		quitButton = new GenericObject(384, 160, 192, 64);
		playAgainIndicator = new GenericObject(640, 288, 64, 64);
		resumeIndicator = new GenericObject(576, 288, 64, 64);
		quitIndicator = new GenericObject(512, 160, 64, 64);
		
		random = new Random();
	}

	@Override
	public void update(float deltaTime) {
		List<KeyEvent> keyEvents = game.getInput().getKeyEvents();
		List<TouchEvent> touchEvents = game.getInput().getTouchEvents();

		if (state == GameState.Ready)
			updateReady(keyEvents, touchEvents);
		if (state == GameState.Running)
			updateRunning(deltaTime, keyEvents, touchEvents);
		if (state == GameState.Paused)
			updatePaused(keyEvents, touchEvents);
		if (state == GameState.GameOver)
			updateGameOver(keyEvents, touchEvents);

	}

	private void updateReady(List<KeyEvent> keyEvents, List<TouchEvent> touchEvents) {
		if(keyEvents.size() > 0 || touchEvents.size() > 0)
			state = GameState.Running;
	}

	private void updateRunning(float deltaTime, List<KeyEvent> keyEvents, List<TouchEvent> touchEvents) {
		world.update(deltaTime);
		world.poop.update(deltaTime);
		
		if(world.gameOver) {
            if(Settings.soundEnabled)
                Assets.playSound(Assets.bitten);
            state = GameState.GameOver;
            gameOverTime = System.currentTimeMillis();
        }
        if(oldScore != world.score) {
            oldScore = world.score;
            score = "" + oldScore;
            if(Settings.soundEnabled)
                Assets.playSound(Assets.eat);
        }

		int len = touchEvents.size();
		for(int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if(event.type != TouchEvent.TOUCH_UP)
				continue;

			touchPoint.set(event.x, event.y);
			guiCam.touchToWorld(touchPoint);

			//touch pause button
			if(OverlapTester.pointInRectangle(pauseButton.bounds, touchPoint)) {
				Assets.playSound(Assets.bark);
				state = GameState.Paused;
				return;
			}

			//touch sound button
			if(OverlapTester.pointInRectangle(soundButton.bounds, touchPoint)) {
				if (Settings.soundEnabled) {
					Settings.soundEnabled = false;
				} else {
					Settings.soundEnabled = true;
					Assets.playSound(Assets.eat);
				}
				return;
			}
			
			if (OverlapTester.pointInRectangle(new Rectangle(world.poop.x * 64 - 32, world.poop.y * 64 -32, 64, 64), touchPoint)) {
				if (random.nextInt(10) > 5) {
					Assets.playSound(Assets.stinky);
				} else {
					Assets.playSound(Assets.squish);
				}
			}
		}
		
		processKeyEvents(keyEvents);
		processTouchEvents(touchEvents);
	}

	private void updatePaused(List<KeyEvent> keyEvents, List<TouchEvent> touchEvents) {
		int len = touchEvents.size();
		for(int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			//if(event.type != TouchEvent.TOUCH_UP)
			//	continue;

			touchPoint.set(event.x, event.y);
			guiCam.touchToWorld(touchPoint);
			
			if (event.type != TouchEvent.TOUCH_UP) {
	        	//lastMenu = _menuSelection;
	        	
	        	//Play
		        if(OverlapTester.pointInRectangle(resumeButton.bounds, touchPoint)) {
		        	_menuSelection = MenuSelection.Resume;
		        }
		        
		        //Quit
		        if(OverlapTester.pointInRectangle(quitButton.bounds, touchPoint)) {
		        	_menuSelection = MenuSelection.Quit;
		        }
	        }
			
			if (event.type == TouchEvent.TOUCH_UP) {
				//resume game
				if(OverlapTester.pointInRectangle(resumeButton.bounds, touchPoint)) {
					Assets.playSound(Assets.bark);
					state = GameState.Running;
					return;
				}
				
				//quite game
				if (OverlapTester.pointInRectangle(quitButton.bounds, touchPoint)) {
					glGame.finish();
				}
			}
		}
		
		//process key events
		len = keyEvents.size();
		for (int i = 0; i < len; i++) {
    		KeyEvent event = keyEvents.get(i);
    		switch (event.keyCode) {
    		case KeyEvent.KEYCODE_DPAD_UP:
    			_menuSelection = MenuSelection.Resume;
    			break;
		    case KeyEvent.KEYCODE_DPAD_DOWN:
		    	_menuSelection = MenuSelection.Quit;
		    	break;
		    case KeyEvent.KEYCODE_DPAD_CENTER:
		    	if (_menuSelection == MenuSelection.Quit)
		    		glGame.finish();
		    	else
		    		state = GameState.Running;
		    	break;
		    
    		}
    	}
	}

	private void updateGameOver(List<KeyEvent> keyEvents, List<TouchEvent> touchEvents) {
		if (!gameOverDelayReached && System.currentTimeMillis() - gameOverTime > GAMEOVER_DELAY) {
			gameOverDelayReached = true;
			_menuSelection = MenuSelection.PlayAgain;
		}
		
		if (gameOverDelayReached) {
			int len = touchEvents.size();
			for(int i = 0; i < len; i++) {
				TouchEvent event = touchEvents.get(i);
				touchPoint.set(event.x, event.y);
				guiCam.touchToWorld(touchPoint);
				
				if (event.type != TouchEvent.TOUCH_UP) {
		        	//Play Again
			        if(OverlapTester.pointInRectangle(playAgainButton.bounds, touchPoint)) {
			        	_menuSelection = MenuSelection.PlayAgain;
			        }
			        
			        //Quit
			        if(OverlapTester.pointInRectangle(quitButton.bounds, touchPoint)) {
			        	_menuSelection = MenuSelection.Quit;
			        }
		        }
				
				if (event.type == TouchEvent.TOUCH_UP) {
					//resume game
					if(OverlapTester.pointInRectangle(playAgainButton.bounds, touchPoint)) {
						Assets.playSound(Assets.bark);
						game.setScreen(new SlugPug(game));
						return;
					}
					
					//quite game
					if (OverlapTester.pointInRectangle(quitButton.bounds, touchPoint)) {
						glGame.finish();
					}
				}
			}
			
			//process key events
			len = keyEvents.size();
			for (int i = 0; i < len; i++) {
	    		KeyEvent event = keyEvents.get(i);
	    		switch (event.keyCode) {
	    		case KeyEvent.KEYCODE_DPAD_UP:
	    			_menuSelection = MenuSelection.PlayAgain;
	    			break;
			    case KeyEvent.KEYCODE_DPAD_DOWN:
			    	_menuSelection = MenuSelection.Quit;
			    	break;
			    case KeyEvent.KEYCODE_DPAD_CENTER:
			    	if (_menuSelection == MenuSelection.Quit)
			    		glGame.finish();
			    	else
			    		game.setScreen(new SlugPug(game));
			    	break;
			    
	    		}
	    	}
		}
	}

	private void processKeyEvents(List<KeyEvent> keyEvents) {
		int len = keyEvents.size();
		for (int i = 0; i < len; i++) {
			KeyEvent event = keyEvents.get(i);
			
			//Up and Down are reversed for some reason in Landscape mode
			switch (event.keyCode) {
			case KeyEvent.KEYCODE_DPAD_UP:
				world.dog.turnDown();
				break;
			case KeyEvent.KEYCODE_DPAD_DOWN:
				world.dog.turnUp();
				break;
			case KeyEvent.KEYCODE_DPAD_LEFT:
				world.dog.turnLeft();
				break;
			case KeyEvent.KEYCODE_DPAD_RIGHT:
				world.dog.turnRight();
				break;
			case KeyEvent.KEYCODE_MEDIA_PAUSE:
				state = GameState.Paused;
				break;
			case KeyEvent.KEYCODE_MEDIA_PLAY:
				state = GameState.Running;
				break;
			default:
				break;
			}
		}
	}

	private void processTouchEvents(List<TouchEvent> touchEvents) {
		int len = touchEvents.size();
		for(int i = 0; i < len; i++) {
			TouchEvent event = touchEvents.get(i);
			if(event.type == TouchEvent.TOUCH_UP) {
				//--SWIPE--//
				deltaX = event.x - initialX;  
				deltaY = event.y - initialY;  

				//swiped up  
				if(deltaY<0 && Math.abs(deltaY)>= Math.abs(deltaX))  
				{  
					world.dog.turnDown();
				}
				//swiped down
				else if (deltaY>0 && Math.abs(deltaY)>= Math.abs(deltaX))  
				{  
					world.dog.turnUp();
				}  
				//swiped right  
				if(deltaX>0 && Math.abs(deltaX)>= Math.abs(deltaY))  
				{  
					world.dog.turnRight();
				}
				//swiped left
				else if (deltaX<0 && Math.abs(deltaX)>= Math.abs(deltaY))
				{
					world.dog.turnLeft();
				}  
			}
			if(event.type == TouchEvent.TOUCH_DOWN) {
				//reset deltaX and deltaY  
				deltaX = deltaY = 0;  

				//get initial positions  
				initialX = event.x;  
				initialY = event.y;
			}
		}
	}

	@Override
	public void present(float deltaTime) {
		GL10 gl = glGraphics.getGL();
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		gl.glEnable(GL10.GL_TEXTURE_2D);

		renderer.render();

		if (state == GameState.Ready)
			presentReady();
		if (state == GameState.Running)
			presentRunning();
		if (state == GameState.Paused)
			presentPaused();
		if (state == GameState.GameOver)
			presentGameOver();

		guiCam.setViewportAndMatrices();
		gl.glDisable(GL10.GL_BLEND);

	}

	private void presentReady() {
		batcher.beginBatch(Assets.pugItems);
		batcher.drawSprite(384, 224, 384, 128, Assets.readyButton);
		batcher.endBatch();
	}

	private void presentRunning() {
		batcher.beginBatch(Assets.pugItems);
			drawHUD();
		batcher.endBatch();
	}

	private void presentPaused() {
		batcher.beginBatch(Assets.pugItems);
			drawHUD();
			batcher.drawSprite(resumeButton.position.x, resumeButton.position.y, resumeButton.width, resumeButton.height, Assets.resumeButton);
			batcher.drawSprite(quitButton.position.x, quitButton.position.y, quitButton.width, quitButton.height, Assets.quitButton);
			
			if (_menuSelection == MenuSelection.Resume) 
				batcher.drawSprite(resumeIndicator.position.x, resumeIndicator.position.y, resumeIndicator.width, resumeIndicator.height, Assets.pawPrint);
			else
				batcher.drawSprite(quitIndicator.position.x, quitIndicator.position.y, quitIndicator.width, quitIndicator.height, Assets.pawPrint);
		batcher.endBatch();
	}

	private void presentGameOver() {
		batcher.beginBatch(Assets.pugItems);
			drawHUD();
			if (!gameOverDelayReached) {
				batcher.drawSprite(384, 224, 448, 64, Assets.gameOver);
			} else {
				batcher.drawSprite(playAgainButton.position.x, playAgainButton.position.y, playAgainButton.width, playAgainButton.height, Assets.playAgain);
				batcher.drawSprite(quitButton.position.x, quitButton.position.y, quitButton.width, quitButton.height, Assets.quitButton);
				
				if (_menuSelection == MenuSelection.PlayAgain)
					batcher.drawSprite(playAgainIndicator.position.x, playAgainIndicator.position.y, playAgainIndicator.width, playAgainIndicator.height, Assets.pawPrint);
				else
					batcher.drawSprite(quitIndicator.position.x, quitIndicator.position.y, quitIndicator.width, quitIndicator.height, Assets.pawPrint);
			}
		batcher.endBatch();
	}
	
	public void drawScore(SpriteBatcher batcher, String score, int x, int y, int numWidth, int numHeight) {
        int len = score.length();
        for (int i = 0; i < len; i++) {
            char character = score.charAt(i);
            
            int offsetX = Integer.parseInt(String.valueOf(character)) * numWidth;
            batcher.drawSprite(x, y, offsetX, 0, numWidth, numHeight, Assets.numbers);
            x += numWidth;
        }
    }
	
	private void drawHUD() {
		TextureRegion sound = null;
		if (Settings.soundEnabled) {
			sound = Assets.soundOnButton;
		} else {
			sound = Assets.soundOffButton;
		}
		
		//draw dirt
		batcher.drawSprite(400, 416, 800, 64, Assets.dirtPatch);
		
		//draw buttons
		batcher.drawSprite(soundButton.position.x, soundButton.position.y, soundButton.width, soundButton.height, sound);
		batcher.drawSprite(pauseButton.position.x, pauseButton.position.y, pauseButton.width, pauseButton.height, Assets.pauseButtonRound);
		
		//draw score
		drawScore(batcher, score, 384, 416, 64, 64);
	}

	@Override
	public void pause() {
		if(state == GameState.Running)
            state = GameState.Paused;
		//pause music
		if (Settings.soundEnabled && Assets.music.isPlaying())
			Assets.music.pause();
	}

	@Override
	public void resume() {
		if (Settings.soundEnabled && !Assets.music.isPlaying())
			Assets.music.play();
	}

	@Override
	public void dispose() {


	}

}
